package com.ihr360.validation;

import com.ihr360.commons.exception.Ihr360Exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.Map;

/**
 * Utility class offering convenient methods for invoking a {@link Validator}
 * and for rejecting empty fields.
 */
public abstract class ValidationUtils {
    private static final Logger logger = LoggerFactory.getLogger(ValidationUtils.class);

    public static void invokeValidator(Validator validator, Object obj) {
        Assert.notNull(validator, "Validator must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking validator [" + validator + "]");
        }
        if (obj != null && !validator.supports(obj.getClass())) {
            throw new IllegalArgumentException(
                    "Validator [" + validator.getClass() + "] does not support [" + obj.getClass() + "]");
        }
        validator.validate(obj);
    }



    public static void rejectIfTrue(boolean expression,String errorCode,String defaultMessage){
        if (expression){
            reject(errorCode,defaultMessage);
        }
    }

    public static void rejectIfEmpty(
            Collection<?> collection, String errorCode, String defaultMessage) {
        if (CollectionUtils.isEmpty(collection)) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectIfEmpty(
            Object value, String errorCode, String defaultMessage) {
        if (value == null || !StringUtils.hasLength(value.toString())) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectIfZero(
            Long value, String errorCode, String defaultMessage) {
        if (value == null || value == 0) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectIfEmpty(
            Map value, String errorCode, String defaultMessage) {
        if (value == null || value.size() == 0) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectIfNotEqual(
            Object value, Object anotherValue, String errorCode, String defaultMessage) {
        rejectIfEmpty(value, errorCode, defaultMessage);
        rejectIfEmpty(anotherValue, errorCode, defaultMessage);
        if (!value.equals(anotherValue) || !StringUtils.hasLength(value.toString())) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectNotEqual(String errorCode, String defaultMessage, Object value, Object... anotherValues) {
        rejectIfEmpty(value, errorCode, defaultMessage);
        boolean expression = false;
        for (Object anotherValue : anotherValues) {
            if(value.equals(anotherValue)) {
                expression = true;
                break;
            }
        }
        if(!expression) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectIfAnyNull(String errorCode, String defaultMessage, Object... values) {
        if (values == null || values.length <= 0) {
            reject(errorCode, defaultMessage);
            return;
        }
        for (Object value : values) {
            if (value == null) {
                reject(errorCode, defaultMessage);
                break;
            }
        }
    }

    public static void rejectIfAllNull(String errorCode, String defaultMessage, Object... values) {
        if (values == null || values.length <= 0) {
            reject(errorCode, defaultMessage);
            return;
        }
        boolean isAllNull = true;
        for (Object value : values) {
            if (value != null) {
                isAllNull = false;
                break;
            }
        }
        if (isAllNull) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectNotGt(
            int value, int rangeLeft, String errorCode, String defaultMessage) {
        if (value < rangeLeft) {
            reject(errorCode, defaultMessage);
        }
    }


    public static void rejectNotLt(
            int value, int rangeRight, String errorCode, String defaultMessage) {
        if (value > rangeRight) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectGt(
            int value, int rangeLeft, String errorCode, String defaultMessage) {
        if (value > rangeLeft) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectLt(
            int value, int rangeRight, String errorCode, String defaultMessage) {
        if (value < rangeRight) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectNotInRange(
            int value, int rangeLeft, int rangeRight, String errorCode, String defaultMessage) {
        if (value < rangeLeft || value > rangeRight) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectNotInRange(
            long value, long rangeLeft, long rangeRight, String errorCode, String defaultMessage) {
        if (value < rangeLeft || value > rangeRight) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectNotInRange(
            double value, double rangeLeft, double rangeRight, String errorCode, String defaultMessage) {
        if (value < rangeLeft || value > rangeRight) {
            reject(errorCode, defaultMessage);
        }
    }

    public static void rejectNotEquals(
            Object value, Object anotherValue, String errorCode, String defaultMessage) {
        if (value == null || anotherValue == null) {
            reject(errorCode, defaultMessage);
        }
        if (!value.equals(anotherValue)) {
            reject(errorCode, defaultMessage);
        }
    }


    public static void rejectIfEmpty(
            Object value, String errorCode, Object[] errorArgs, String defaultMessage) {
        if (value == null || !StringUtils.hasLength(value.toString())) {
            reject(errorCode, defaultMessage, errorArgs);
        }
    }

    public static void rejectIfEmptyOrWhitespace(
            Object value, String errorCode, String defaultMessage) {
        rejectIfEmptyOrWhitespace(value, errorCode, null, defaultMessage);
    }

    public static void rejectIfEmptyOrWhitespace(
            Object value, String errorCode, Object[] errorArgs, String defaultMessage) {
        if (value == null || !StringUtils.hasText(value.toString())) {
            reject(errorCode, defaultMessage, errorArgs);
        }
    }

    public static void reject(
            String errorCode, String defaultMessage) {
        throw new Ihr360Exception(errorCode, defaultMessage);
    }

    public static void reject(
            String errorCode, String defaultMessage, Object[] errorArgs) {
        throw new Ihr360Exception(errorCode, defaultMessage, errorArgs);
    }
}